package com.eastfair.venueservice.service.impl;

import cn.hutool.core.bean.BeanUtil;
//import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eastfair.auth.api.AuthServiceFeign;
import com.eastfair.auth.api.UserAccountServiceFeign;
import com.eastfair.auth.dto.OrganizationDTO;
import com.eastfair.auth.dto.UserAccountDto;
import com.eastfair.auth.vo.OrganizationVo;
import com.eastfair.auth.vo.UserAccountVo;
import com.eastfair.boot.request.PageParams;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.common.dto.AttachmentFileDTO;
import com.eastfair.common.vo.AttachmentFileVO;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.constant.BusinessInnerMsgTemplate;
import com.eastfair.core.base.R;
import com.eastfair.core.base.entity.SuperEntity;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.context.StaticContextUtil;
import com.eastfair.core.exception.BizException;
import com.eastfair.core.utils.ConvertUtil;
import com.eastfair.core.utils.ExcelUtils;
import com.eastfair.messagecenter.util.SendMsgUtil;
import com.eastfair.pay.api.AttachmentFileFeign;
import com.eastfair.projectcore.enumeration.DataIsolationSystemSceneEnum;
import com.eastfair.venueservice.consts.CommonConstants;
import com.eastfair.venueservice.dao.ServiceInventoryMapper;
import com.eastfair.venueservice.dao.ServiceItemMapper;
import com.eastfair.venueservice.dto.*;
import com.eastfair.venueservice.entity.*;
import com.eastfair.venueservice.enumeration.ServiceBookingOrderStatusEnum;
import com.eastfair.venueservice.enumeration.ServiceInventoryInFlowInStockTypeEnum;
import com.eastfair.venueservice.enumeration.ServiceItemAuditStateEnum;
import com.eastfair.venueservice.enumeration.ServiceItemServiceStateEnum;
import com.eastfair.venueservice.enums.VenueServicesManageModuleEnum;
import com.eastfair.venueservice.exceptioncode.VenueServiceExceptionCode;
import com.eastfair.venueservice.service.*;
import com.eastfair.venueservice.vo.*;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 业务实现类
 * 服务项
 * </p>
 *
 * @author linan
 * @date 2022-07-13
 */
@Slf4j
@Service
//@DS("#thread.tenant")
public class ServiceItemServiceImpl extends SuperServiceImpl<ServiceItemMapper, ServiceItem> implements ServiceItemService {

    public static final String SERVICE_NO = "service_no";
    public static final String SI = "SI";
    public static final String INVENTORY_CODE = "inventory_code";
    public static final String IC = "IC";
    @Resource
    private AttachmentFileFeign attachmentFileFeign;
    @Resource
    private ServiceItemDetailService serviceItemDetailService;
    @Resource
    private ServiceInventoryService serviceInventoryService;
    @Resource
    private ServiceInventoryMapper serviceInventoryMapper;
    @Resource
    private ServiceCategoryService serviceCategoryService;
    @Resource
    private ServiceSpecsService serviceSpecsService;
    @Resource
    private ServiceProviderService serviceProviderService;
    @Resource
    private AuthServiceFeign authServiceFeign;
    @Resource
    private ServicePriceListItemService servicePriceListItemService;
    @Resource
    private ServiceItemDiscountService serviceItemDiscountService;
    @Resource
    private UserAccountServiceFeign userAccountServiceFeign;
    @Resource
    private ServiceBookingService serviceBookingService;
    @Resource
    private ExhibitionServiceProviderService exhibitionServiceProviderService;
    @Resource
    private ExhibitionManageService exhibitionManageService;
    @Resource
    private ServiceInventoryInFlowService serviceInventoryInFlowService;
    @Resource
    private SendMsgUtil sendMsgUtil;
    @Resource
    private VenueManageDictionaryService venueManageDictionaryService;
    @Resource
    private ServiceItemOrgService serviceItemOrgService;

    @Resource(name = "threadPoolTaskExecutor")
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;



    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<ServiceItem> modelList) {
        modelList.stream().forEach(s -> {
            s.setIsDeleted(BusinessConstant.YES);
        });
        // TODO: 2021/10/29 这里需要操作其他业务，如清空角色等
        return R.successDef();
    }

    @Override
    protected R<Boolean> handlerSave(ServiceItem model) {
        model.setProjectId(ContextUtil.getProjectId());
        model.setSubsystemId(ContextUtil.getSubSystemId());
        model.setTenantId(ContextUtil.getTenantId());
        return R.successDef();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<Boolean> addServiceItem(ServiceItemDTO serviceItemDTO) {
        // 防止脏数据，先删除
        if (Objects.nonNull(serviceItemDTO.getSourceId()) && serviceItemDTO.getSourceId() != 0) {
            List<ServiceItem> list = list(new QueryWrapper<ServiceItem>().lambda().eq(ServiceItem::getIsDeleted, BusinessConstant.NO).eq(ServiceItem::getSourceId, serviceItemDTO.getSourceId()));
            for (ServiceItem serviceItem : list) {
                ServiceItemDTO itemDTO = new ServiceItemDTO();
                itemDTO.setId(serviceItem.getId());
                delServiceItem(itemDTO, false);
            }
        }
        // 转成entity
        ServiceItem serviceItem = BeanUtil.copyProperties(serviceItemDTO, ServiceItem.class);
        // 判断供应商类型
        serviceItem.setServiceProviderType(Strings.isNotBlank(serviceItem.getServiceProviderType()) ? serviceItem.getServiceProviderType() : ContextUtil.getSystemScene());
        serviceItem.setSourceProvider(Strings.isNotBlank(serviceItem.getSourceProvider()) ? serviceItem.getSourceProvider() : ContextUtil.getSystemScene());
        String serviceProviderType = serviceItem.getServiceProviderType();
        // 如果供应商类型是 "综合-配套商管理"，则审核状态为"未审核"，其他情况为已审核
        if (DataIsolationSystemSceneEnum.P_COMPOSITE_MATING.getCode().equals(serviceProviderType)) {
            serviceItem.setAuditState(ServiceItemAuditStateEnum.NOT_APPROVED);
        } else {
            serviceItem.setAuditState(ServiceItemAuditStateEnum.APPROVED);
        }
        // 生成服务编号
        serviceItem.setServiceNo(CreatCode.creatCode(baseMapper, SERVICE_NO,10, SI));
        // 处理服务部门
        if(CollectionUtils.isEmpty(serviceItemDTO.getServiceProviderIds())){
            serviceItemDTO.setServiceProviderIds(Collections.singletonList(serviceItemDTO.getServiceProviderId()));
        }
        List<Long> serviceProviderIds = serviceItemDTO.getServiceProviderIds();
        serviceItem.setServiceProviderId(serviceProviderIds.get(0));
        boolean result = save(serviceItem);
        for (Long serviceProviderId : serviceProviderIds) {
            ServiceItemOrg serviceItemOrg = new ServiceItemOrg();
            serviceItemOrg.setServiceItemId(serviceItem.getId());
            serviceItemOrg.setServiceProviderId(serviceProviderId);
            serviceItemOrgService.save(serviceItemOrg);
        }
        // 处理服务图片
        dealServicePic(serviceItemDTO, serviceItem);
        // 处理服务明细、服务库存
        dealDetailAndInventory(serviceItemDTO, serviceItem, serviceItem.getId());
        // 如果是主场添加，还需要处理折扣利率
        serviceItemDiscountService.saveDiscount(serviceItem,serviceItemDTO.getServiceItemDiscountList());
        // 配套商添加服务，发送消息提醒场馆用户审核
        if (DataIsolationSystemSceneEnum.P_COMPOSITE_MATING.getCode().equals(serviceProviderType)) {
            asyncSendMatchingServiceSubmitInnerMsg(serviceItemDTO);
        }
        return R.success(result);
    }

    /**
     * 处理服务图片
     * @param serviceItemDTO
     * @param serviceItem
     * @return
     */
    private void dealServicePic(ServiceItemDTO serviceItemDTO, ServiceItem serviceItem) {
        List<AttachmentFileDTO> picList = CollectionUtils.isNotEmpty(serviceItemDTO.getPicList()) ? serviceItemDTO.getPicList() : new ArrayList<>();
        if(CollectionUtils.isNotEmpty(picList)){
            serviceItem.setPicUrl(picList.get(0).getAttachmentUrl());
        }
        Long id = serviceItem.getId();
        for (AttachmentFileDTO attachmentFileDTO : picList) {
            attachmentFileDTO.setId(null);
            attachmentFileDTO.setBusinessId(id);
            attachmentFileDTO.setBusinessType(VenueServicesManageModuleEnum.SERVICE_ITEM.getCode());
        }
        R r = attachmentFileFeign.addAttachmentFile(picList);
        if (!r.getIsSuccess()) {
            throw new BizException(r.getCode(), r.getMsg());
        }
    }

    @Override
    public void syncServiceItem(Long exhibitionId, ServicePriceListVO data, DataIsolationSystemSceneEnum sceneEnum,Long serviceProviderId) {
        // 查询现有服务,且来源与综合的服务
        List<ServiceItem> oldList = list(new QueryWrapper<ServiceItem>().lambda()
                .eq(ServiceItem::getServiceProviderId, serviceProviderId)
                .eq(ServiceItem::getExhibitionManageId, exhibitionId)
                .eq(ServiceItem::getSourceProvider, DataIsolationSystemSceneEnum.P_COMPOSITE_VENUE)
                .eq(ServiceItem::getServiceProviderType, sceneEnum.getCode())
                .eq(ServiceItem::getIsDeleted, BusinessConstant.NO));
        Map<Long, ServiceItem> oldServiceItemMap = oldList.stream().collect(Collectors.toMap(ServiceItem::getSourceId, Function.identity()));
        List<ServicePriceListItemVO> servicePriceListItems = data.getServicePriceListItem();
        if(CollectionUtils.isNotEmpty(servicePriceListItems)){
            for (ServicePriceListItemVO servicePriceListItem : servicePriceListItems) {
                List<ServicePriceListDetailVO> servicePriceListDetailList = servicePriceListItem.getServicePriceListDetailList();
                syncServiceItemAndDetail(servicePriceListItem, sceneEnum, exhibitionId, servicePriceListDetailList,serviceProviderId,oldServiceItemMap);
            }
        }
        oldServiceItemMap.values().forEach(e->{
            ServiceItemDTO serviceItemDTO = new ServiceItemDTO();
            serviceItemDTO.setId(e.getId());
            delServiceItem(serviceItemDTO,false);
        });
    }

    /**
     * 通过服务分类的id查询服务项数量
     * @param serviceCategoryId
     * @param serviceProviderId
     * @return
     */
    @Override
    public Integer getServiceItemSumByCategoryId(Long serviceCategoryId, Long serviceProviderId) {
        List<ServiceItem> list = Lists.newArrayList();
        QueryWrapper<ServiceItem> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(ServiceItem::getIsDeleted,BusinessConstant.DELETE_NO)
                .eq(ServiceItem::getServiceCategoryId,serviceCategoryId)
                .eq(ServiceItem::getAuditState,ServiceItemAuditStateEnum.APPROVED)
                .eq(Objects.nonNull(serviceProviderId),ServiceItem::getServiceProviderId,serviceProviderId)
                .eq(ServiceItem::getServiceProviderType,ContextUtil.getSystemScene());
        list=this.list(queryWrapper);
        int sum = list.size() == 0 ? 0 : list.size();
        return sum;
    }

    @Override
    public List<ServiceItemVO> queryServiceItemOfSubscribe(PageParams<ServiceItemQuery> serviceItemQuery) {
        serviceItemQuery.setOrder("ascending");
        serviceItemQuery.setSort("convert(a.service_name using gbk)");
        // todo 通过搭建商，查询主场
        ServiceItemQuery model = serviceItemQuery.getModel();
        String systemScene = ContextUtil.getSystemScene();
        if (DataIsolationSystemSceneEnum.P_COMPOSITE_PRODUCER.getCode().equals(systemScene)) {
            model.setServiceProviderType(DataIsolationSystemSceneEnum.P_COMPOSITE_COURT.getCode());
        }
        QueryWrapper<ServiceItem> wrapper = new QueryWrapper<>();
        wrapper.in(CollectionUtils.isNotEmpty(model.getServiceCategoryId()),"a.service_category_id",model.getServiceCategoryId())
                .like(StringUtils.isNotBlank(model.getServiceName()),"a.service_name",model.getServiceName())
                .eq("a.service_state",ServiceItemServiceStateEnum.ON_SHELVES.getCode())
                .eq("a.audit_state",ServiceItemAuditStateEnum.APPROVED.getCode())
                .eq(Objects.nonNull(model.getServiceProviderId()),"a.service_provider_id",model.getServiceProviderId())
                .eq("a.service_provider_type",model.getServiceProviderType())
                .eq(Objects.nonNull(model.getIsManage()), "d.is_manage", model.getIsManage())
                .eq(Objects.nonNull(model.getExhibitionManageId()),"a.exhibition_manage_id",model.getExhibitionManageId())
                .eq("a.is_deleted",BusinessConstant.NO)
                .eq("a.is_enabled",BusinessConstant.YES);
        List<ServiceItemWithDetailVO> detailList = baseMapper.listServiceItemWithDetail(wrapper, model.getReportSpaceId());
        Map<Long, List<ServiceItemWithDetailVO>> collect = detailList.stream().collect(Collectors.groupingBy(ServiceItemWithDetailVO::getServiceItemId, Collectors.toList()));
        List<ServiceItemVO> serviceItemVOS = new ArrayList<>();
        collect.forEach((key, value) -> {
            ServiceItemVO serviceItemVO = new ServiceItemVO();
            ServiceItemWithDetailVO serviceItemWithDetailVO = value.get(0);
            BeanUtil.copyProperties(serviceItemWithDetailVO, serviceItemVO);
            serviceItemVO.setId(serviceItemWithDetailVO.getServiceItemId());
            serviceItemVO.setMinAllocatedNum(serviceItemWithDetailVO.getMinBookNum());
            serviceItemVO.setServiceItemDetailVOList(ConvertUtil.convertList(value,ServiceItemDetailVO.class));
            serviceItemVOS.add(serviceItemVO);
        });
        return serviceItemVOS;
    }

    @Override
    public List<ServiceItemVO> queryServiceItemOfTransport(ServiceItemQuery serviceItemQuery) {
        LocalDateTime now = LocalDateTime.now();
        QueryWrapper<ServiceItem> wrapper = new QueryWrapper<>();
        wrapper.eq("b.is_for_transport" , BusinessConstant.YES)
                .eq("a.is_deleted" , BusinessConstant.NO)
                .eq("b.is_deleted" , BusinessConstant.NO)
                .eq("c.is_deleted" , BusinessConstant.NO)
                .eq("e.service_provider_type" , "P_COMPOSITE_VENUE")
                .eq(Objects.nonNull(serviceItemQuery.getExhibitionManageId()),"d.id" , serviceItemQuery.getExhibitionManageId())
                .in(CollectionUtils.isNotEmpty(serviceItemQuery.getServiceCategoryId()),"e.service_category_id",serviceItemQuery.getServiceCategoryId());
        ArrayList<ServiceItemVO> serviceItemVOS = getServiceItemVOS(wrapper, serviceItemQuery, now);
        return serviceItemVOS;
    }

    @NotNull
    private ArrayList<ServiceItemVO> getServiceItemVOS(QueryWrapper<ServiceItem> wrapper, ServiceItemQuery serviceItemQuery, LocalDateTime now) {
        List<ServiceItemWithDetailVO> detailList = baseMapper.queryServiceItemOfTransport(wrapper, serviceItemQuery.getOrderNumber());
        Map<Long, List<ServiceItemWithDetailVO>> collect = detailList.stream().collect(Collectors.groupingBy(ServiceItemWithDetailVO::getServiceItemId, Collectors.toList()));
        ArrayList<ServiceItemVO> serviceItemVOS = new ArrayList<>();
        collect.forEach((key, value) -> {
            ServiceItemVO serviceItemVO = new ServiceItemVO();
            ServiceItemWithDetailVO serviceItemWithDetailVO = value.get(0);
            BeanUtil.copyProperties(serviceItemWithDetailVO, serviceItemVO);
            serviceItemVO.setId(serviceItemWithDetailVO.getServiceItemId());
            serviceItemVO.setMinAllocatedNum(serviceItemWithDetailVO.getMinBookNum());
            // 处理折扣
            for (ServiceItemWithDetailVO itemWithDetailVO : value) {
                String orderStatus = itemWithDetailVO.getOrderStatus();
                if(StringUtils.isBlank(orderStatus)
                        || ServiceBookingOrderStatusEnum.CANCEL.getCode().equals(orderStatus)
                        ||  ServiceBookingOrderStatusEnum.NOT_SUBMIT.getCode().equals(orderStatus) ){
                    LocalDateTime preDiscountStartTime = itemWithDetailVO.getPreDiscountStartTime();
                    LocalDateTime preDiscountEndTime = itemWithDetailVO.getPreDiscountEndTime();
                    LocalDateTime onDiscountStartTime = itemWithDetailVO.getOnDiscountStartTime();
                    LocalDateTime onDiscountEndTime = itemWithDetailVO.getOnDiscountEndTime();
                    if (Objects.nonNull(preDiscountStartTime) && Objects.nonNull(preDiscountEndTime) && now.compareTo(preDiscountStartTime) >= 0 && now.compareTo(preDiscountEndTime) <= 0) {
                        itemWithDetailVO.setDiscount(itemWithDetailVO.getPreExhibitionDiscount());
                    } else if (Objects.nonNull(onDiscountStartTime) && Objects.nonNull(onDiscountEndTime) && now.compareTo(onDiscountStartTime) >= 0 && now.compareTo(onDiscountEndTime) <= 0) {
                        itemWithDetailVO.setDiscount(itemWithDetailVO.getOnSiteDiscount());
                    }
                }
            }
            serviceItemVO.setServiceItemDetailVOList(ConvertUtil.convertList(value,ServiceItemDetailVO.class));
            serviceItemVOS.add(serviceItemVO);
        });
        return serviceItemVOS;
    }

    @Override
    public List<ServiceItemVO> queryServiceItemOfSponsor(ServiceItemQuery serviceItemQuery) {
        LocalDateTime now = LocalDateTime.now();
        QueryWrapper<ServiceItem> wrapper = new QueryWrapper<>();
        wrapper.eq("b.is_for_sponsor" , BusinessConstant.YES)
                .eq("a.is_deleted" , BusinessConstant.NO)
                .eq("b.is_deleted" , BusinessConstant.NO)
                .eq("c.is_deleted" , BusinessConstant.NO)
                .eq("e.service_provider_type" , "P_COMPOSITE_VENUE")
                .eq(Objects.nonNull(serviceItemQuery.getExhibitionManageId()),"d.id" , serviceItemQuery.getExhibitionManageId())
                .in(CollectionUtils.isNotEmpty(serviceItemQuery.getServiceCategoryId()),"e.service_category_id",serviceItemQuery.getServiceCategoryId());
        ArrayList<ServiceItemVO> serviceItemVOS = getServiceItemVOS(wrapper, serviceItemQuery, now);
        return serviceItemVOS;
    }

    @Override
    public List<ServiceItem> listBySourceIdList(List<Long> sourceIdList) {
        log.info("listBySourceIdList - 来源服务ID列表查询服务项列表, sourceIdList={}", sourceIdList);
        QueryWrapper<ServiceItem> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(ServiceItem::getIsDeleted, BusinessConstant.DELETE_NO)
                .in(sourceIdList != null && !sourceIdList.isEmpty(), ServiceItem::getSourceId, sourceIdList)
        ;
        return list(queryWrapper);
    }

    @Override
    public List<ServiceItemVO> queryServiceItemOfVenue(ServiceItemQuery serviceItemQuery) {
        LocalDateTime now = LocalDateTime.now();
        QueryWrapper<ServiceItem> wrapper = new QueryWrapper<>();
        wrapper.eq("e.is_deleted" , BusinessConstant.NO)
                .eq("f.is_deleted" , BusinessConstant.NO)
                .eq("e.service_provider_type" , DataIsolationSystemSceneEnum.P_COMPOSITE_VENUE.getCode())
                .eq("e.service_state" , ServiceItemServiceStateEnum.ON_SHELVES.getCode())
                .in(CollectionUtils.isNotEmpty(serviceItemQuery.getServiceCategoryId()),"e.service_category_id",serviceItemQuery.getServiceCategoryId());
        List<ServiceItemWithDetailVO> detailList = baseMapper.queryServiceItemOfVenue(wrapper, serviceItemQuery.getOrderNumber());
        ExhibitionManage exhibitionManage = exhibitionManageService.getById(serviceItemQuery.getExhibitionManageId());
        Map<Long, List<ServiceItemWithDetailVO>> collect = detailList.stream().collect(Collectors.groupingBy(ServiceItemWithDetailVO::getServiceItemId, Collectors.toList()));
        ArrayList<ServiceItemVO> serviceItemVOS = new ArrayList<>();
        collect.forEach((key, value) -> {
            ServiceItemVO serviceItemVO = new ServiceItemVO();
            ServiceItemWithDetailVO serviceItemWithDetailVO = value.get(0);
            BeanUtil.copyProperties(serviceItemWithDetailVO, serviceItemVO);
            serviceItemVO.setId(serviceItemWithDetailVO.getServiceItemId());
            serviceItemVO.setMinAllocatedNum(serviceItemWithDetailVO.getMinBookNum());
            // 处理折扣
            for (ServiceItemWithDetailVO itemWithDetailVO : value) {
                String orderStatus = itemWithDetailVO.getOrderStatus();
                if(StringUtils.isBlank(orderStatus)
                        || ServiceBookingOrderStatusEnum.CANCEL.getCode().equals(orderStatus)
                        ||  ServiceBookingOrderStatusEnum.NOT_SUBMIT.getCode().equals(orderStatus) ){
                    LocalDateTime preDiscountStartTime = exhibitionManage.getPreDiscountStartTime();
                    LocalDateTime preDiscountEndTime = exhibitionManage.getPreDiscountEndTime();
                    LocalDateTime onDiscountStartTime = exhibitionManage.getOnDiscountStartTime();
                    LocalDateTime onDiscountEndTime = exhibitionManage.getOnDiscountEndTime();
                    if (Objects.nonNull(preDiscountStartTime) && Objects.nonNull(preDiscountEndTime) && now.compareTo(preDiscountStartTime) >= 0 && now.compareTo(preDiscountEndTime) <= 0) {
                        itemWithDetailVO.setDiscount(itemWithDetailVO.getPreExhibitionDiscount());
                    } else if (Objects.nonNull(onDiscountStartTime) && Objects.nonNull(onDiscountEndTime) && now.compareTo(onDiscountStartTime) >= 0 && now.compareTo(onDiscountEndTime) <= 0) {
                        itemWithDetailVO.setDiscount(itemWithDetailVO.getOnSiteDiscount());
                    }
                }
            }
            serviceItemVO.setServiceItemDetailVOList(ConvertUtil.convertList(value,ServiceItemDetailVO.class));
            serviceItemVOS.add(serviceItemVO);
        });
        return serviceItemVOS;
    }

    @Override
    public ServiceItem getDeapSourceServiceItem(Long sourceId) {
        ServiceItem serviceItem = getById(sourceId);
        if (Objects.nonNull(serviceItem) && Objects.nonNull(serviceItem.getSourceId())) {
            return getDeapSourceServiceItem(serviceItem.getSourceId());
        } else {
            return serviceItem;
        }
    }

    @Override
    public void warning(ServiceOrder serviceOrder) {
        threadPoolTaskExecutor.execute(() -> {
            Long exhibitionManageId = serviceOrder.getExhibitionManageId();
            waringByExhibitionManageId(exhibitionManageId);
        });
    }

    @Override
    public void waring(Long homeId, Long exhibitionManageId) {
        threadPoolTaskExecutor.execute(() -> waringByExhibitionManageId(exhibitionManageId));
    }

    @Override
    public boolean sendMatchingServiceSubmitInnerMsg(ServiceItemDTO serviceItem) {
        log.info("sendMatchingServiceSubmitInnerMsg - 发送配套上服务提交审核的站内信, serviceItem={}", serviceItem);
        ServiceProvider serviceProvider = serviceProviderService.getById(serviceItem.getServiceProviderId());
        if (serviceProvider == null) {
            log.info("sendMatchingServiceSubmitInnerMsg - 配套商缺失，无法发送站内信");
            return false;
        }
        String content = String.format(BusinessInnerMsgTemplate.SERVICE_AUDIT_TEMPLATE, serviceProvider.getCompanyName());
        sendMsgUtil.sendInnerMsg(content, StaticContextUtil.getProjectSystemScene());
        return true;
    }

    @Override
    public void asyncSendMatchingServiceSubmitInnerMsg(ServiceItemDTO serviceItem) {
        threadPoolTaskExecutor.execute(() -> sendMatchingServiceSubmitInnerMsg(serviceItem));
    }

    private void waringByExhibitionManageId(Long exhibitionManageId) {
        // 查询展会需要告警的服务规格项
        if (Objects.nonNull(exhibitionManageId)) {
            List<ServiceInventoryVO> serviceInventoryVOS = serviceInventoryService.queryWaringItem(exhibitionManageId);
            for (ServiceInventoryVO serviceInventoryVO : serviceInventoryVOS) {
                String content =String.format("%s，%s，库存剩余数量小于%s,请及时处理！",serviceInventoryVO.getServiceName(),serviceInventoryVO.getServiceSpecsName(),serviceInventoryVO.getEarlyWarningValue().setScale(0, RoundingMode.DOWN));
                log.info(content);
                sendMsgUtil.sendInnerMsg(content, StaticContextUtil.getProjectSystemScene());
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<Boolean> syncServiceItem(ServiceItemDTO serviceItemDTO) {
        Long serviceProviderId = serviceItemDTO.getServiceProviderId();
        String serviceProviderType = serviceItemDTO.getServiceProviderType();
        // 查询展会和价目
        List<ExhibitionServiceProvider> list = exhibitionServiceProviderService.list(new QueryWrapper<ExhibitionServiceProvider>().lambda()
                .eq(ExhibitionServiceProvider::getServiceProviderId, serviceProviderId)
                .eq(Objects.nonNull(serviceItemDTO.getExhibitionManageId()),ExhibitionServiceProvider::getExhibitionManageId, serviceItemDTO.getExhibitionManageId())
                .eq(ExhibitionServiceProvider::getIsDeleted, BusinessConstant.NO));
        if(CollectionUtils.isNotEmpty(list)){
            for (ExhibitionServiceProvider exhibitionServiceProvider : list) {
                Long exhibitionManageId = exhibitionServiceProvider.getExhibitionManageId();
                // 同步主场/主运服务
                R<ServicePriceListVO> servicePriceListVOR = servicePriceListItemService.queryPriceListByExhibition(ServicePriceListQuery.builder().exhibitionManageId(exhibitionManageId).build());
                ServicePriceListVO data = servicePriceListVOR.getData();
                if(Objects.nonNull(data)){
                    syncServiceItem(exhibitionManageId,data,DataIsolationSystemSceneEnum.valueOf(serviceProviderType),serviceProviderId);
                }
            }

        }
        return R.success(true);
    }

    @Override
    public void exportServiceItem(ServiceItemDTO serviceItemDTO, HttpServletResponse response) throws Exception {
        // 查询同步给服务商的服务
        List<ServiceItemDetailVO> itemDetails =  baseMapper.queryVenueServiceItem(serviceItemDTO);
        List<Map<String, Object>> rows = new ArrayList<>();
        // 数据字典
        Map<String, String> calUnitDict = venueManageDictionaryService.queryDictMap("SERVICE_MEASUREMENT_UNIT");
        for (ServiceItemDetailVO serviceItemVO: itemDetails) {
            TreeMap<String, Object> map = new TreeMap<>((o1, o2) -> 1);
            map.put("服务分类id", serviceItemVO.getServiceCategoryId().toString());
            map.put("服务分类名称", serviceItemVO.getServiceCategoryName());
            map.put("服务项id", serviceItemVO.getServiceItemId().toString());
            map.put("服务项名称", serviceItemVO.getServiceName());
            map.put("服务项单价", serviceItemVO.getUnitPrice());
            map.put("服务项押金", serviceItemVO.getSurcharge());
            map.put("服务项规格id", serviceItemVO.getServiceSpecsId().toString());
            map.put("服务项规格", serviceItemVO.getServiceCategoryName());
            map.put("服务项计量单位",calUnitDict.get(serviceItemVO.getCalUnit()));
            map.put("服务项备注", serviceItemVO.getRemark());
            rows.add(map);
        }
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition","attachment;filename=场馆服务.xlsx");
        try (ServletOutputStream out = response.getOutputStream()) {
            ExcelUtils.export(rows, out);
        }
    }

    @Override
    public List<Long> queryCategoryIds(Long exhibitionManageId) {
        return baseMapper.queryCategoryIds(exhibitionManageId);
    }

    /**
     * 同步服务项和明细
     * @param servicePriceListItem servicePriceListItem
     * @param sceneEnum sceneEnum
     * @param exhibitionId exhibitionId
     * @param servicePriceListDetailList servicePriceListDetailList
     * @param serviceProviderId
     * @param oldServiceItemMap
     */
    private void syncServiceItemAndDetail(ServicePriceListItemVO servicePriceListItem, DataIsolationSystemSceneEnum sceneEnum, Long exhibitionId, List<ServicePriceListDetailVO> servicePriceListDetailList, Long serviceProviderId, Map<Long, ServiceItem> oldServiceItemMap) {
        Long serviceItemId = servicePriceListItem.getServiceItemId();
        // 老主场服务
        ServiceItem oldServiceItem = oldServiceItemMap.get(serviceItemId);
        ServiceItem serviceItemOld = getById(serviceItemId);
        // 同步服务项
        ServiceItem serviceItem = BeanUtil.copyProperties(serviceItemOld, ServiceItem.class, CommonConstants.COMMON_IGNORE_PROPERTIES);
        serviceItem.setSourceId(serviceItemId);
        serviceItem.setSourceProvider(DataIsolationSystemSceneEnum.P_COMPOSITE_VENUE.getCode());
        // 生成服务编号
        serviceItem.setServiceNo(CreatCode.creatCode(baseMapper, SERVICE_NO,10, SI));
        // 供应商类型
        serviceItem.setServiceProviderType(sceneEnum.getCode());
        // 服务商id
        if(Objects.nonNull(serviceProviderId)){
            serviceItem.setServiceProviderId(serviceProviderId);
        }
        serviceItem.setAuditState(ServiceItemAuditStateEnum.APPROVED);
        // 服务状态 待上架
        serviceItem.setServiceState(ServiceItemServiceStateEnum.DEFAULT);
        // 展会id
        serviceItem.setExhibitionManageId(exhibitionId);
        // enable状态处理
        dealEnabled(servicePriceListItem, sceneEnum, serviceItem);
        List<ServiceItem> serviceItems = new ArrayList<>();
        // 保存服务
        if (Objects.nonNull(oldServiceItem)) {
            // 删除附件
            R<List<AttachmentFileVO>> listR = attachmentFileFeign.queryAttachmentFile(AttachmentFileDTO.builder().isDeleted(BusinessConstant.NO).businessId(serviceItemId).build());
            attachmentFileFeign.deteleBatch(listR.getData().stream().map(AttachmentFileVO::getId).collect(Collectors.toList()));
            serviceItem.setId(oldServiceItem.getId());
            updateById(serviceItem);
            // 删除服务明细和库存
            delDetailAndInventory(serviceItem.getId());
            // 移除map值
            oldServiceItemMap.remove(serviceItemId);
        } else {
            handlerSave(serviceItem);
            serviceItems.add(serviceItem);
//            save(serviceItem);
        }
        if(serviceItems.size() > 0){
            saveBatch(serviceItems);
        }
        Long id = serviceItem.getId();
        // 处理服务部门
        ServiceItemOrg serviceItemOrg = new ServiceItemOrg();
        serviceItemOrg.setServiceItemId(id);
        serviceItemOrg.setServiceProviderId(serviceProviderId);
        serviceItemOrgService.save(serviceItemOrg);
        // 查询所有服务附件
        AttachmentFileDTO queryDTO = AttachmentFileDTO.builder().businessId(serviceItemId).isDeleted(BusinessConstant.NO).businessType(VenueServicesManageModuleEnum.SERVICE_ITEM.getCode()).build();
        R<List<AttachmentFileVO>> listR = attachmentFileFeign.queryAttachmentFile(queryDTO);
        List<AttachmentFileDTO> attachmentFileDTOS = new ArrayList<>();
        for (AttachmentFileVO vo : listR.getData()) {
            AttachmentFileDTO attachmentFileDTO = BeanUtil.copyProperties(vo, AttachmentFileDTO.class);
            attachmentFileDTO.setBusinessId(id);
            attachmentFileDTO.setBusinessType(VenueServicesManageModuleEnum.SERVICE_ITEM.getCode());
            attachmentFileDTOS.add(attachmentFileDTO);
        }
        R r = attachmentFileFeign.addAttachmentFile(attachmentFileDTOS);
        if (!r.getIsSuccess()) {
            throw new BizException(r.getCode(), r.getMsg());
        }
        // 处理服务明细、服务库存
        dealDetailAndInventoryByPrice(servicePriceListDetailList, id);
    }

    /**
     * 删除明细和库存
     * @param serviceItemId
     */
    private void delDetailAndInventory(Long serviceItemId) {
        serviceItemDetailService.update(new UpdateWrapper<ServiceItemDetail>().lambda()
                .eq(ServiceItemDetail::getIsDeleted,BusinessConstant.NO)
                .eq(ServiceItemDetail::getServiceItemId, serviceItemId)
                .set(ServiceItemDetail::getIsDeleted,BusinessConstant.YES));
        serviceInventoryService.update(new UpdateWrapper<ServiceInventory>().lambda()
                .eq(ServiceInventory::getIsDeleted,BusinessConstant.NO)
                .eq(ServiceInventory::getServiceItemId, serviceItemId)
                .set(ServiceInventory::getIsDeleted,BusinessConstant.YES));
    }

    private void dealEnabled(ServicePriceListItemVO servicePriceListItem, DataIsolationSystemSceneEnum sceneEnum, ServiceItem serviceItem) {
        if (DataIsolationSystemSceneEnum.P_COMPOSITE_COURT.eq(sceneEnum)) {
            Integer isForHome = servicePriceListItem.getIsForHome();
            if (BusinessConstant.YES == isForHome) {
                serviceItem.setIsEnabled(BusinessConstant.YES);
            } else {
                serviceItem.setIsEnabled(BusinessConstant.NO);
            }
        } else if (DataIsolationSystemSceneEnum.P_COMPOSITE_TRANSPORT.eq(sceneEnum)) {
            Integer isForTransport = servicePriceListItem.getIsForTransport();
            if (BusinessConstant.YES == isForTransport) {
                serviceItem.setIsEnabled(BusinessConstant.YES);
            } else {
                serviceItem.setIsEnabled(BusinessConstant.NO);
            }
        }
    }

    /**
     * 通过价目表同步服务明细
     * @param servicePriceListDetailList servicePriceListDetailList
     * @param id id
     */
    private void dealDetailAndInventoryByPrice(List<ServicePriceListDetailVO> servicePriceListDetailList, Long id) {
        if(CollectionUtils.isNotEmpty(servicePriceListDetailList)){
            for (ServicePriceListDetailVO servicePriceListDetailVO : servicePriceListDetailList) {
                ServiceItemDetail serviceItemDetail = BeanUtil.copyProperties(servicePriceListDetailVO, ServiceItemDetail.class,"id");
                serviceItemDetail.setServiceItemId(id);
                serviceItemDetailService.save(serviceItemDetail);
                ServiceInventory serviceInventory = BeanUtil.copyProperties(servicePriceListDetailVO, ServiceInventory.class,"id");
                serviceInventory.setServiceItemId(id);
                // 生成服务编号
                serviceInventory.setInventoryCode(CreatCode.creatCode(serviceInventoryMapper, INVENTORY_CODE,10, IC));
                serviceInventoryService.save(serviceInventory);
                // 初始化流水
                ServiceInventoryInFlowDTO serviceInventoryInFlow = BeanUtil.copyProperties(serviceInventory, ServiceInventoryInFlowDTO.class, CommonConstants.COMMON_IGNORE_PROPERTIES);
                serviceInventoryInFlow.setInNum(serviceInventory.getInventoryNum());
                serviceInventoryInFlow.setInStockType(ServiceInventoryInFlowInStockTypeEnum.INIT);
                serviceInventoryInFlowService.saveInFlow(serviceInventoryInFlow);
            }
        }
    }

    private void dealDetailAndInventory(ServiceItemDTO serviceItemDTO, ServiceItem serviceItem, Long id) {
        if(CollectionUtils.isNotEmpty(serviceItemDTO.getServiceItemDetailList())){
            for (ServiceItemDetailDTO serviceItemDetailDTO : serviceItemDTO.getServiceItemDetailList()) {
                ServiceItemDetail serviceItemDetail = BeanUtil.copyProperties(serviceItemDetailDTO, ServiceItemDetail.class);
                serviceItemDetail.setServiceItemId(id);
                serviceItemDetail.setServiceCategoryId(serviceItem.getServiceCategoryId());
                serviceItemDetailService.save(serviceItemDetail);
                ServiceInventory serviceInventory = BeanUtil.copyProperties(serviceItemDetailDTO, ServiceInventory.class);
                serviceInventory.setServiceItemId(id);
                serviceInventory.setServiceCategoryId(serviceItem.getServiceCategoryId());
                // 生成库存编号
                serviceInventory.setInventoryCode(CreatCode.creatCode(serviceInventoryMapper, INVENTORY_CODE,10, IC));
                serviceInventoryService.save(serviceInventory);
                // 初始化流水
                ServiceInventoryInFlowDTO serviceInventoryInFlow = BeanUtil.copyProperties(serviceInventory, ServiceInventoryInFlowDTO.class, CommonConstants.COMMON_IGNORE_PROPERTIES);
                serviceInventoryInFlow.setInNum(serviceInventory.getInventoryNum());
                serviceInventoryInFlow.setInStockType(ServiceInventoryInFlowInStockTypeEnum.INIT);
                serviceInventoryInFlowService.saveInFlow(serviceInventoryInFlow);
            }
        }
    }

    @Override
    public void addServiceItemAfterAudit(Long id) {
        ServiceItem serviceItem = this.getById(id);
        if(Objects.nonNull(serviceItem)){
            ServiceItemDTO serviceItemDTO = BeanUtil.copyProperties(serviceItem, ServiceItemDTO.class);
            serviceItemDTO.setId(null);
            serviceItemDTO.setSourceId(serviceItem.getId());
            serviceItemDTO.setServiceProviderType(DataIsolationSystemSceneEnum.P_COMPOSITE_VENUE.getCode());
            serviceItemDTO.setSourceProvider(DataIsolationSystemSceneEnum.P_COMPOSITE_MATING.getCode());
            // 服务附件
            R<List<AttachmentFileVO>> listR = attachmentFileFeign.queryAttachmentFile(AttachmentFileDTO.builder().businessId(id).isDeleted(BusinessConstant.NO).businessType(VenueServicesManageModuleEnum.SERVICE_ITEM.getCode()).build());
            List<AttachmentFileVO> data = listR.getData();
            if(CollectionUtils.isNotEmpty(data)){
                List<AttachmentFileDTO> attachmentFileDTOS = ConvertUtil.convertList(data, AttachmentFileDTO.class);
                serviceItemDTO.setPicList(attachmentFileDTOS);
            }
            // 服务明细和库存
            List<ServiceItemDetail> oldServiceItemDetailList =  serviceItemDetailService.list(new QueryWrapper<ServiceItemDetail>()
                    .lambda()
                    .eq(ServiceItemDetail::getIsDeleted, BusinessConstant.NO)
                    .eq(ServiceItemDetail::getServiceItemId, serviceItem.getId()));
            List<ServiceItemDetailDTO> serviceItemDetailDTOS = new ArrayList<>();
            if(CollectionUtils.isNotEmpty(oldServiceItemDetailList)){
                List<ServiceInventory> serviceInventories = serviceInventoryService.list(new QueryWrapper<ServiceInventory>().lambda().eq(ServiceInventory::getServiceItemId,serviceItem.getId()).eq(ServiceInventory::getIsDeleted,BusinessConstant.NO));
                Map<String, ServiceInventory> serviceInventoryMap = serviceInventories.stream().collect(Collectors.toMap(e -> e.getServiceItemId() + "_" + e.getServiceCategoryId() + "_" + e.getServiceSpecsId(), Function.identity()));
                for (ServiceItemDetail serviceItemDetail : oldServiceItemDetailList) {
                    ServiceItemDetailDTO serviceItemDetailDTO = BeanUtil.copyProperties(serviceItemDetail, ServiceItemDetailDTO.class,"id");
                    ServiceInventory serviceInventory = serviceInventoryMap.get(serviceItemDetail.getServiceItemId() + "_" + serviceItemDetail.getServiceCategoryId() + "_" + serviceItemDetail.getServiceSpecsId());
                    if(Objects.nonNull(serviceInventory)){
                        serviceItemDetailDTO.setInventoryNum(serviceInventory.getInventoryNum());
                        serviceItemDetailDTO.setEarlyWarningValue(serviceInventory.getEarlyWarningValue());
                    }
                    serviceItemDetailDTOS.add(serviceItemDetailDTO);
                }
            }
            serviceItemDTO.setServiceItemDetailList(serviceItemDetailDTOS);
            addServiceItem(serviceItemDTO);
        }
    }

    @Override
    public List<ServiceItemVO> queryServiceItemSimpleList(ServiceItemQuery serviceItemQuery) {
        QueryWrapper<ServiceItem> serviceItemQueryWrapper = new QueryWrapper<>();
        serviceItemQueryWrapper.lambda().like(StringUtils.isNotBlank(serviceItemQuery.getServiceName()),ServiceItem::getServiceName,serviceItemQuery.getServiceName())
                .eq(StringUtils.isNotBlank(serviceItemQuery.getServiceProviderType()),ServiceItem::getServiceProviderType,serviceItemQuery.getServiceProviderType())
                .eq(ServiceItem::getIsDeleted,BusinessConstant.NO);
        return ConvertUtil.convertList(list(serviceItemQueryWrapper),ServiceItemVO.class);
    }

    @Override
    public void removeByExhibition(Long exhibitionManageId, List<DataIsolationSystemSceneEnum> scene) {
        // 查询展会下、所属系统下的服务
        List<ServiceItem> list = list(new QueryWrapper<ServiceItem>().lambda()
                .eq(ServiceItem::getIsDeleted, BusinessConstant.NO)
                .eq(ServiceItem::getExhibitionManageId, exhibitionManageId)
                .in(ServiceItem::getServiceProviderType, scene.stream().map(DataIsolationSystemSceneEnum::getCode).collect(Collectors.toList()))
                .eq(ServiceItem::getSourceProvider, DataIsolationSystemSceneEnum.P_COMPOSITE_VENUE.getCode()));
        if(CollectionUtils.isNotEmpty(list)){
            // 服务走删除接口，依次删除
            for (ServiceItem serviceItem : list) {
                ServiceItemDTO serviceItemDTO = new ServiceItemDTO();
                serviceItemDTO.setId(serviceItem.getId());
                delServiceItem(serviceItemDTO,true);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<Boolean> updateServiceItem(ServiceItemDTO serviceItemDTO) {
        Long id = serviceItemDTO.getId();
        ServiceItem serviceItem = getById(serviceItemDTO.getId());
        // 非下架状态不可修改
        if (Objects.isNull(serviceItem) || ServiceItemServiceStateEnum.ON_SHELVES.eq(serviceItem.getServiceState())){
            throw BizException.wrap(VenueServiceExceptionCode.SERVICES_CANT_UPDATE);
        }
        // 删除原附件
        dealFiles(serviceItemDTO, id);
        // 服务明细和库存的特殊处理
        dealDetailAndInventory(serviceItemDTO);
        // 如果是配套服务项，需要先删除下游服务，发起新的审核
        if(DataIsolationSystemSceneEnum.P_COMPOSITE_MATING.getCode().equals(serviceItem.getServiceProviderType())){
            // 查询是否存在下游服务
            List<ServiceItem> afterServiceItems = list(new QueryWrapper<ServiceItem>().lambda().eq(ServiceItem::getSourceId, serviceItemDTO.getId()).eq(ServiceItem::getIsDeleted, BusinessConstant.NO));
            for (ServiceItem afterServiceItem : afterServiceItems) {
                if (Objects.nonNull(afterServiceItem)) {
                    ServiceItemDTO copyServiceItemDTO = new ServiceItemDTO();
                    copyServiceItemDTO.setId(afterServiceItem.getId());
                    // 循环处理
                    delServiceItem(copyServiceItemDTO,false);
                }
            }
            serviceItemDTO.setAuditState(ServiceItemAuditStateEnum.NOT_APPROVED);
        }
        // 处理服务部门
        if(CollectionUtils.isEmpty(serviceItemDTO.getServiceProviderIds())){
            serviceItemDTO.setServiceProviderIds(Collections.singletonList(serviceItemDTO.getServiceProviderId()));
        }
        serviceItemOrgService.update(new UpdateWrapper<ServiceItemOrg>().lambda()
                .eq(ServiceItemOrg::getServiceItemId,serviceItem.getId())
                .eq(ServiceItemOrg::getIsDeleted, BusinessConstant.NO)
                .set(ServiceItemOrg::getIsDeleted, BusinessConstant.YES));
        List<Long> serviceProviderIds = serviceItemDTO.getServiceProviderIds();
        serviceItemDTO.setServiceProviderId(serviceProviderIds.get(0));
        for (Long serviceProviderId : serviceProviderIds) {
            ServiceItemOrg serviceItemOrg = new ServiceItemOrg();
            serviceItemOrg.setServiceItemId(serviceItem.getId());
            serviceItemOrg.setServiceProviderId(serviceProviderId);
            serviceItemOrgService.save(serviceItemOrg);
        }
        boolean result = updateById(BeanUtil.copyProperties(serviceItemDTO, ServiceItem.class));
        // 如果是主场添加，还需要处理折扣利率
        serviceItemDiscountService.saveDiscount(serviceItem,serviceItemDTO.getServiceItemDiscountList());
        // 更新未生成订单的服务预订
        serviceBookingService.updateByItem(serviceItemDTO);
        return R.success(result);
    }



    @Override
    public R<Boolean> updateServiceItemInventory(ServiceItemDTO serviceItemDTO) {
        ServiceItem serviceItem = getById(serviceItemDTO.getId());
        // 非下架状态不可修改
        if (Objects.isNull(serviceItem) || ServiceItemServiceStateEnum.ON_SHELVES.eq(serviceItem.getServiceState())){
            throw BizException.wrap(VenueServiceExceptionCode.SERVICES_CANT_UPDATE);
        }
        // 服务明细和库存的特殊处理
        dealDetailAndInventory(serviceItemDTO);
        // todo 更新未生成订单的服务预订
        serviceItemDTO.setPicUrl(serviceItemDTO.getPicUrl());
        serviceItemDTO.setServiceName(serviceItemDTO.getServiceName());
        serviceItemDTO.setCalUnit(serviceItemDTO.getCalUnit());
        serviceBookingService.updateByItem(serviceItemDTO);
        return R.success();
    }

    /**
     * 处理附件
     * @param serviceItemDTO
     * @param id
     */
    private void dealFiles(ServiceItemDTO serviceItemDTO, Long id) {
        R<List<AttachmentFileVO>> listR = attachmentFileFeign.queryAttachmentFile(AttachmentFileDTO.builder().businessId(id).isDeleted(BusinessConstant.NO).businessType(VenueServicesManageModuleEnum.SERVICE_ITEM.getCode()).build());
        if (!listR.getIsSuccess()) {
            throw new BizException(listR.getCode(), listR.getMsg());
        }
        List<Long> ids = listR.getData().stream().map(AttachmentFileVO::getId).collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(ids)){
            attachmentFileFeign.deteleBatch(ids);
        }
        List<AttachmentFileDTO> picList = serviceItemDTO.getPicList();
        for (AttachmentFileDTO attachmentFileDTO : picList) {
            if(Strings.isBlank(serviceItemDTO.getPicUrl())){
                serviceItemDTO.setPicUrl(attachmentFileDTO.getAttachmentUrl());
            }
            attachmentFileDTO.setId(null);
            attachmentFileDTO.setBusinessId(id);
            attachmentFileDTO.setBusinessType(VenueServicesManageModuleEnum.SERVICE_ITEM.getCode());
        }
        R r = attachmentFileFeign.addAttachmentFile(picList);
        if (!r.getIsSuccess()) {
            throw new BizException(r.getCode(), r.getMsg());
        }
    }

    /**
     * 服务明细和库存的特殊处理
     * @param serviceItemDTO serviceItemDTO
     */
    private void dealDetailAndInventory(ServiceItemDTO serviceItemDTO) {
        // 查询原规格明细
        List<ServiceItemDetail> oldServiceItemDetailList =  serviceItemDetailService.list(new QueryWrapper<ServiceItemDetail>()
                .lambda()
                .eq(ServiceItemDetail::getIsDeleted, BusinessConstant.NO)
                .eq(ServiceItemDetail::getServiceItemId, serviceItemDTO.getId()));
        Map<Long, ServiceItemDetail> oldServiceItemDetailMap = oldServiceItemDetailList.stream().collect(Collectors.toMap(ServiceItemDetail::getServiceSpecsId, Function.identity()));
        List<ServiceItemDetailDTO> serviceItemDetailList = serviceItemDTO.getServiceItemDetailList();
        Map<Long, ServiceItemDetailDTO> serviceItemDetailDtoMap = serviceItemDetailList.stream().collect(Collectors.toMap(ServiceItemDetailDTO::getServiceSpecsId, Function.identity()));
        // 查询原服务规格库存
        List<ServiceInventory> oldServiceInventoryList =  serviceInventoryService.list(new QueryWrapper<ServiceInventory>()
                .lambda()
                .eq(ServiceInventory::getIsDeleted, BusinessConstant.NO)
                .eq(ServiceInventory::getServiceItemId, serviceItemDTO.getId()));
        Map<Long, ServiceInventory> oldServiceDetailMap = oldServiceInventoryList.stream().collect(Collectors.toMap(ServiceInventory::getServiceSpecsId, Function.identity()));
        serviceItemDetailDtoMap.forEach((key, value) -> {
            // 判断是否已存在该规格明细数据
            ServiceItemDetail oldServiceItemDetail = oldServiceItemDetailMap.get(key);
            ServiceItemDetail serviceItemDetail = BeanUtil.copyProperties(value, ServiceItemDetail.class);
            serviceItemDetail.setServiceItemId(serviceItemDTO.getId());
            if(Objects.nonNull(oldServiceItemDetail)){
                // 如果存在则用原ID修改
                serviceItemDetail.setId(oldServiceItemDetail.getId());
                serviceItemDetailService.updateById(serviceItemDetail);
            }else {
                // 如果是不存在的规格，则直接新增
                serviceItemDetailService.save(serviceItemDetail);
            }
            // 判断是否已存在改规格库存
            ServiceInventory oldServiceInventory = oldServiceDetailMap.get(key);
            ServiceInventory serviceInventory = BeanUtil.copyProperties(value, ServiceInventory.class);
            serviceInventory.setServiceItemId(serviceItemDTO.getId());
            if(Objects.nonNull(oldServiceInventory)){
                // 如果存在则用原ID修改
                serviceInventory.setId(oldServiceInventory.getId());
                serviceInventoryService.updateById(serviceInventory);
                // 作废就的初始入库数量
                serviceInventoryInFlowService.update(new UpdateWrapper<ServiceInventoryInFlow>().lambda()
                        .eq(ServiceInventoryInFlow::getInventoryCode,oldServiceInventory.getInventoryCode())
                        .eq(ServiceInventoryInFlow::getIsDeleted,BusinessConstant.NO)
                        .set(ServiceInventoryInFlow::getBeforeInventoryNum,oldServiceInventory.getInventoryNum())
                        .set(ServiceInventoryInFlow::getInNum,serviceInventory.getInventoryNum())
                        .set(ServiceInventoryInFlow::getAfterInventoryNum,serviceInventory.getInventoryNum()));
            }else {
                // 如果是不存在的规格，则直接新增
                // 处理库存编号
                serviceInventory.setInventoryCode(CreatCode.creatCode(serviceInventoryMapper, INVENTORY_CODE,10, IC));
                serviceInventoryService.save(serviceInventory);
                // 初始化流水
                ServiceInventoryInFlowDTO serviceInventoryInFlow = BeanUtil.copyProperties(serviceInventory, ServiceInventoryInFlowDTO.class, CommonConstants.COMMON_IGNORE_PROPERTIES);
                serviceInventoryInFlow.setInNum(serviceInventory.getInventoryNum());
                serviceInventoryInFlow.setInStockType(ServiceInventoryInFlowInStockTypeEnum.INIT);
                serviceInventoryInFlowService.saveInFlow(serviceInventoryInFlow);
            }
            oldServiceItemDetailMap.remove(key);
        });
        // 历史的，修改时删除了，则数据进行软删
        List<ServiceItemDetail> collect = new ArrayList<>(oldServiceItemDetailMap.values());
        serviceItemDetailService.removeByIdsOfLogic(collect);
    }

    @Override
    public IPage<ServiceItemVO> queryServiceItem(PageParams<ServiceItemQuery> serviceItemQuery) {
        // 默认倒叙
        serviceItemQuery.setOrder("descending");
        serviceItemQuery.setSort("createTime");
        ServiceItemQuery model = serviceItemQuery.getModel();
        QueryWrapper<ServiceItem> itemQueryWrapper = new QueryWrapper<>();
        packageWrapper(model, itemQueryWrapper);
        Page<ServiceItem> page = serviceItemQuery.buildPage();
        page = page(page, itemQueryWrapper);
        Page<ServiceItemVO> resultPage = serviceItemQuery.buildPage();
        BeanUtils.copyProperties(page, resultPage);
        // 如果没数据就直接返回了
        if (CollectionUtils.isEmpty(page.getRecords())) {
            return resultPage;
        }
        // 获取所有服务ID
        List<Long> serviceItemIds = page.getRecords().stream().map(ServiceItem::getId).collect(Collectors.toList());
        // 查询所有服务分类和分类规格
        List<Long> serviceCategoryIds = page.getRecords().stream().map(ServiceItem::getServiceCategoryId).collect(Collectors.toList());
        List<ServiceCategory> serviceCategories = serviceCategoryService.listByIds(serviceCategoryIds);
        Map<Long, String> serviceCategoryMap = serviceCategories.stream().collect(Collectors.toMap(ServiceCategory::getId,ServiceCategory::getServiceCategoryName));
        List<ServiceSpecs> serviceSpecsList = serviceSpecsService.list(new QueryWrapper<ServiceSpecs>().lambda()
                .in(ServiceSpecs::getServiceCategoryId, serviceCategoryIds)
                .eq(ServiceSpecs::getIsDeleted,BusinessConstant.NO));
        Map<Long, String> serviceSpecsMap = serviceSpecsList.stream().collect(Collectors.toMap(ServiceSpecs::getId, ServiceSpecs::getServiceSpecsName));

        // 查询所有服务明细
        List<ServiceItemDetail> serviceItemDetails = serviceItemDetailService.list(new QueryWrapper<ServiceItemDetail>().lambda()
                .in(ServiceItemDetail::getServiceItemId,serviceItemIds)
                .eq(ServiceItemDetail::getIsDeleted,BusinessConstant.NO));
        // 查询所有服务库存
        List<ServiceInventory> serviceInventories = serviceInventoryService.list(new QueryWrapper<ServiceInventory>().lambda().in(ServiceInventory::getServiceItemId,serviceItemIds).eq(ServiceInventory::getIsDeleted,BusinessConstant.NO));
        Map<String, ServiceInventory> serviceInventoryMap = serviceInventories.stream().collect(Collectors.toMap(e -> e.getServiceItemId() + "_" + e.getServiceCategoryId() + "_" + e.getServiceSpecsId(), Function.identity()));
        List<ServiceItemDetailVO> serviceItemDetailList =  ConvertUtil.convertList(serviceItemDetails, ServiceItemDetailVO.class);
        Map<Long, List<ServiceItemDetailVO>> serviceItemDetailMap = getServiceItemDetailMap(serviceCategoryMap, serviceSpecsMap, serviceInventoryMap, serviceItemDetailList);
        List<ServiceItemVO> serviceItemList = new ArrayList<>();
        // 服务部门、服务商名称 （id全局唯一）
        // 查询服务部门
        List<ServiceItemOrg> serviceItemOrgList = serviceItemOrgService.list(new QueryWrapper<ServiceItemOrg>().lambda().in(ServiceItemOrg::getServiceItemId, serviceItemIds).eq(ServiceItemOrg::getIsDeleted, BusinessConstant.NO));
        Map<Long, List<ServiceItemOrg>> serviceItemOrgListMap = serviceItemOrgList.stream().collect(Collectors.groupingBy(ServiceItemOrg::getServiceItemId));
        List<Long> serviceProviderIds = serviceItemOrgList.stream().map(e->e.getServiceProviderId()).distinct().collect(Collectors.toList());
        Map<Long, String> names = Maps.newHashMap();
        names = getProviderName(serviceProviderIds, names);
        // 服务折扣
        Map<Long,List<ServiceItemDiscountVO>> discountMap = getDiscountMap(serviceItemIds);
        // 审核人名称
        UserAccountDto userAccountDto = new UserAccountDto();
        List<Long> auditByIds = page.getRecords().stream().filter(e->Objects.nonNull(e.getAuditBy()) ).map(ServiceItem::getAuditBy).collect(Collectors.toList());
        HashMap<Long, String> auditByMap = new HashMap<>(8);
        if(CollectionUtils.isNotEmpty(auditByIds)){
            userAccountDto.setUserIds(auditByIds);
            R<List<UserAccountVo>> listR = userAccountServiceFeign.querySimpleByIds(userAccountDto);
            if(CollectionUtils.isNotEmpty(listR.getData())){
                listR.getData().forEach(e->auditByMap.put(e.getId(), e.getRealName()));
            }else {
                log.warn("联系人查询为空 {}",auditByIds);
            }
        }
        packageVO(model, page, serviceCategoryMap, serviceItemDetailMap, serviceItemList, names,discountMap,auditByMap,serviceItemOrgListMap);
        resultPage.setRecords(serviceItemList);
        return resultPage;
    }

    /**
     * 服务折扣map
     * @param serviceItemIds serviceItemIds
     * @return Map<Long, List<ServiceItemDiscountVO>>
     */
    private Map<Long, List<ServiceItemDiscountVO>> getDiscountMap(List<Long> serviceItemIds) {
        // todo 后续考虑是否只有详情时查询，或主场查
        return ConvertUtil.convertList(
                serviceItemDiscountService.list(new QueryWrapper<ServiceItemDiscount>().lambda()
                        .in(ServiceItemDiscount::getServiceItemId, serviceItemIds)
                        .eq(ServiceItemDiscount::getIsDeleted, BusinessConstant.NO)), ServiceItemDiscountVO.class)
                .stream()
                .collect(Collectors.groupingBy(ServiceItemDiscountVO::getServiceItemId));
    }

    /**
     * 封装返回VO
     * @param model model
     * @param page page
     * @param serviceCategoryMap serviceCategoryMap
     * @param serviceItemDetailMap serviceItemDetailMap
     * @param serviceItemList serviceItemList
     * @param names names
     * @param discount discount
     * @param auditByMap
     * @param serviceItemOrgListMap
     */
    private void packageVO(ServiceItemQuery model, Page<ServiceItem> page, Map<Long, String> serviceCategoryMap, Map<Long, List<ServiceItemDetailVO>> serviceItemDetailMap, List<ServiceItemVO> serviceItemList, Map<Long, String> names, Map<Long, List<ServiceItemDiscountVO>> discount, HashMap<Long, String> auditByMap, Map<Long, List<ServiceItemOrg>> serviceItemOrgListMap) {
        for (ServiceItem record : page.getRecords()) {
            ServiceItemVO serviceItemVO = BeanUtil.copyProperties(record, ServiceItemVO.class);
            if (Objects.nonNull(model.getId())) {
                // 查询所有服务附件
                AttachmentFileDTO attachmentFileDTO = AttachmentFileDTO.builder().businessId(record.getId()).isDeleted(BusinessConstant.NO).businessType(VenueServicesManageModuleEnum.SERVICE_ITEM.getCode()).build();
                R<List<AttachmentFileVO>> listR = attachmentFileFeign.queryAttachmentFile(attachmentFileDTO);
                serviceItemVO.setAttachmentFileVOList(listR.getData());
            }
            // 服务明细
            serviceItemVO.setServiceItemDetailVOList(serviceItemDetailMap.get(record.getId()));
            // 服务分类名称
            serviceItemVO.setServiceCategoryName(serviceCategoryMap.get(serviceItemVO.getServiceCategoryId()));
            // 服务供应商名称
            List<ServiceItemOrg> serviceItemOrgs = serviceItemOrgListMap.get(record.getId());
            List<ServiceItemOrgVO> serviceItemOrgVOList = new ArrayList<>();
            if(CollectionUtils.isNotEmpty(serviceItemOrgs)){
                for (ServiceItemOrg serviceItemOrg : serviceItemOrgs) {
                    ServiceItemOrgVO serviceItemOrgVO = BeanUtil.copyProperties(serviceItemOrg, ServiceItemOrgVO.class);
                    serviceItemOrgVO.setServiceProviderName(names.get(serviceItemOrg.getServiceProviderId()));
                    serviceItemOrgVOList.add(serviceItemOrgVO);
                }
            }
            serviceItemVO.setServiceProviderName(names.get(record.getServiceProviderId()));
            serviceItemVO.setServiceItemOrgList(serviceItemOrgVOList);
            // 服务折扣
            serviceItemVO.setServiceItemDiscountVOList(discount.get(record.getId()));
            // 审核人名称
            if(Objects.nonNull(serviceItemVO.getAuditBy())){
                serviceItemVO.setAuditByName(auditByMap.get(serviceItemVO.getAuditBy()));
            }
            serviceItemVO.setOrderNum(0);
            serviceItemList.add(serviceItemVO);
        }
    }

    /**
     * 封装wrapper
     * @param model
     * @param itemQueryWrapper
     */
    private void packageWrapper(ServiceItemQuery model, QueryWrapper<ServiceItem> itemQueryWrapper) {
        List<Long> serviceCategoryIds = new ArrayList<>();
        if(Objects.nonNull(model.getIsManage())){
            List<ServiceCategory> list = serviceCategoryService.list(new QueryWrapper<ServiceCategory>().lambda()
                    .eq(ServiceCategory::getIsManage, model.getIsManage())
                    .eq(ServiceCategory::getIsDeleted, BusinessConstant.NO));
            serviceCategoryIds = list.stream().map(SuperEntity::getId).collect(Collectors.toList());
            if(CollectionUtils.isEmpty(serviceCategoryIds)){
                serviceCategoryIds.add(0L);
            }
        }
        List<Long> serviceItemIds = new ArrayList<>();
        if(Objects.nonNull(model.getServiceProviderId())){
            OrganizationDTO organizationDTO = new OrganizationDTO();
            organizationDTO.setOrgId(model.getServiceProviderId());
            R<List<Long>> listR = authServiceFeign.queryChildOrgIdOfOrgId(organizationDTO);
            List<Long> serviceProviderIds = new ArrayList<>();
            serviceProviderIds.add(model.getServiceProviderId());
            if(listR.getIsSuccess() && CollectionUtils.isNotEmpty(listR.getData()) ){
                serviceProviderIds.addAll(listR.getData());
            }
            serviceItemIds = serviceItemOrgService.list(new QueryWrapper<ServiceItemOrg>().lambda()
                    .eq(ServiceItemOrg::getIsDeleted,BusinessConstant.NO)
                    .in(ServiceItemOrg::getServiceProviderId,serviceProviderIds))
                    .stream().map(ServiceItemOrg::getServiceItemId).collect(Collectors.toList());
            if(CollectionUtils.isEmpty(serviceItemIds)){
                serviceItemIds.add(0L);
            }
        }
        itemQueryWrapper.lambda()
                .eq(ServiceItem::getIsDeleted, BusinessConstant.NO)
                .eq(ServiceItem::getIsEnabled, BusinessConstant.YES)
                .like(StringUtils.isNotBlank(model.getServiceName()), ServiceItem::getServiceName, model.getServiceName())
                .like(StringUtils.isNotBlank(model.getServiceNo()), ServiceItem::getServiceNo, model.getServiceNo())
                .in(CollectionUtils.isNotEmpty(model.getServiceCategoryId()), ServiceItem::getServiceCategoryId, model.getServiceCategoryId())
                .in(Objects.nonNull(model.getServiceProviderId()), ServiceItem::getId, serviceItemIds)
                .eq(Objects.nonNull(model.getId()), ServiceItem::getId, model.getId())
                .eq(Objects.nonNull(model.getServiceState()), ServiceItem::getServiceState, model.getServiceState())
                .eq(Objects.nonNull(model.getServiceProviderType()), ServiceItem::getServiceProviderType, model.getServiceProviderType())
                .eq(Objects.nonNull(model.getSourceProvider()), ServiceItem::getSourceProvider, model.getSourceProvider())
                .in(Objects.nonNull(model.getIsManage()), ServiceItem::getServiceCategoryId, serviceCategoryIds)
                .eq(Objects.nonNull(model.getExhibitionManageId()), ServiceItem::getExhibitionManageId, model.getExhibitionManageId())
                .eq(Objects.nonNull(model.getAuditState()), ServiceItem::getAuditState, model.getAuditState());
    }

    /**
     * 获取服务商或部门名称
     * @param serviceProviderIds serviceProviderIds
     * @param names names
     * @return
     */
    private Map<Long, String> getProviderName(List<Long> serviceProviderIds, Map<Long, String> names) {
        if (CollectionUtils.isNotEmpty(serviceProviderIds)) {
            // 服务商名称
            names = serviceProviderService.listServiceProviderByIds(serviceProviderIds).stream().collect(Collectors.toMap(ServiceProviderVO::getId, ServiceProviderVO::getCompanyName));
            // 部门名称
            List<OrganizationVo> data = authServiceFeign.queryList(serviceProviderIds).getData();
            if(CollectionUtils.isNotEmpty(data)){
                names.putAll(data.stream().collect(Collectors.toMap(OrganizationVo::getId, OrganizationVo::getName)));
            }
        }
        return names;
    }

    /**
     * 获取服务明细关系map
     * @param serviceCategoryMap serviceCategoryMap
     * @param serviceSpecsMap serviceSpecsMap
     * @param serviceInventoryMap serviceInventoryMap
     * @param serviceItemDetailList serviceItemDetailList
     * @return Map<Long, List<ServiceItemDetailVO>>
     */
    private Map<Long, List<ServiceItemDetailVO>> getServiceItemDetailMap(Map<Long, String> serviceCategoryMap, Map<Long, String> serviceSpecsMap, Map<String, ServiceInventory> serviceInventoryMap, List<ServiceItemDetailVO> serviceItemDetailList) {
        return serviceItemDetailList.parallelStream().peek(e -> {
            e.setServiceCategoryName(serviceCategoryMap.get(e.getServiceCategoryId()));
            e.setServiceSpecsName(serviceSpecsMap.get(e.getServiceSpecsId()));
            ServiceInventory serviceInventory = serviceInventoryMap.get(e.getServiceItemId() + "_" + e.getServiceCategoryId() + "_" + e.getServiceSpecsId());
            if (Objects.nonNull(serviceInventory)) {
                e.setInventoryCode(serviceInventory.getInventoryCode());
                e.setInventoryNum(serviceInventory.getInventoryNum());
                e.setEarlyWarningValue(serviceInventory.getEarlyWarningValue());
            }
        }).collect(Collectors.groupingBy(ServiceItemDetailVO::getServiceItemId));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<?> updateServiceItemState(ServiceItemDTO serviceItemDTO) {
        if (ServiceItemServiceStateEnum.ON_SHELVES.eq(serviceItemDTO.getServiceState())) {
            return R.success(upShelves(serviceItemDTO));
        } else if (ServiceItemServiceStateEnum.UNDER_SHELVES.eq(serviceItemDTO.getServiceState())) {
            return R.success(downShelves(serviceItemDTO));
        }
        return R.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<?> delServiceItem(ServiceItemDTO serviceItemDTO,Boolean isPriceCancel) {
        ServiceItem serviceItem = getById(serviceItemDTO.getId());
        // 处于已上架状态下不可删除 (价目取消除外)
        if(!isPriceCancel && (Objects.isNull(serviceItem) || ServiceItemServiceStateEnum.ON_SHELVES.eq(serviceItem.getServiceState()))){
            throw BizException.wrap(VenueServiceExceptionCode.SERVICES_CANT_DELETE);
        }
        // 如果是综合服务，判断是否有绑定价目，且价目被展会使用
        checkExistPriceList(serviceItem);
        // 查询是否存在下游服务
        List<ServiceItem> afterServiceItems = list(new QueryWrapper<ServiceItem>().lambda().eq(ServiceItem::getSourceId, serviceItemDTO.getId()).eq(ServiceItem::getIsDeleted, BusinessConstant.NO));
        for (ServiceItem afterServiceItem : afterServiceItems) {
            if (Objects.nonNull(afterServiceItem)) {
                ServiceItemDTO copyServiceItemDTO = new ServiceItemDTO();
                copyServiceItemDTO.setId(afterServiceItem.getId());
                // 循环处理
                delServiceItem(copyServiceItemDTO,isPriceCancel);
            }
        }
        // 删除服务明细和库存
        delDetailAndInventory(serviceItemDTO.getId());
        // 软删价目
        servicePriceListItemService.removeByServiceItemId(serviceItemDTO.getId());
        return R.success(removeByIdsOfLogic(Collections.singleton(serviceItem)));
    }

    private void checkExistPriceList(ServiceItem serviceItem) {
        if(DataIsolationSystemSceneEnum.P_COMPOSITE_VENUE.getCode().equals(ContextUtil.getSystemScene())){
            Long serviceItemId = serviceItem.getId();
            List<ServicePriceListItem> list = servicePriceListItemService.list(new QueryWrapper<ServicePriceListItem>().lambda()
                    .eq(ServicePriceListItem::getServiceItemId, serviceItemId)
                    .eq(ServicePriceListItem::getIsEnabled, BusinessConstant.YES)
                    .eq(ServicePriceListItem::getIsDeleted, BusinessConstant.NO));
            for (ServicePriceListItem servicePriceListItem : list) {
                boolean b1 = Objects.nonNull(servicePriceListItem.getIsForHome()) && BusinessConstant.YES == servicePriceListItem.getIsForHome();
                boolean b2 = Objects.nonNull(servicePriceListItem.getIsForSponsor()) && BusinessConstant.YES == servicePriceListItem.getIsForSponsor();
                boolean b3 = Objects.nonNull(servicePriceListItem.getIsForTransport()) && BusinessConstant.YES == servicePriceListItem.getIsForTransport();
                if (b1 || b2 || b3) {
                    List<ExhibitionManage> exhibitionManageList = exhibitionManageService.list(new QueryWrapper<ExhibitionManage>().lambda()
                            .eq(ExhibitionManage::getPriceListId, servicePriceListItem.getPriceListId())
                            .eq(ExhibitionManage::getIsDeleted, BusinessConstant.NO));
                    if(CollectionUtils.isNotEmpty(exhibitionManageList)){
                        throw BizException.wrap(VenueServiceExceptionCode.SERVICES_CANT_DELETE_WITH_PRICE_LIST);
                    }
                }
            }
        }
    }

    /**
     * 根据ID查询服务详情信息
     * @param id
     * @return
     */
    @Override
    public ServiceItem getServiceItemById(Long id) {
        ServiceItem serviceItem = this.getById(id);
        return serviceItem;
    }

    /**
     * 上架操作
     * @param serviceItemDTO serviceItemDTO
     * @return Boolean
     */
    private Boolean upShelves(ServiceItemDTO serviceItemDTO) {
        ServiceItem serviceItem = getById(serviceItemDTO.getId());
        if (Objects.nonNull(serviceItem)) {
            // 查询是否存在上游
            if (Objects.nonNull(serviceItem.getSourceId())) {
                ServiceItem beforeServiceItem = getById(serviceItem.getSourceId());
                if (ServiceItemServiceStateEnum.ON_SHELVES.eq(serviceItemDTO.getServiceState()) && Objects.nonNull(beforeServiceItem) && !ServiceItemServiceStateEnum.ON_SHELVES.eq(beforeServiceItem.getServiceState())) {
                    // 上游服务未上架
                    throw BizException.wrap(VenueServiceExceptionCode.UPSTREAM_SERVICES_NOT_AVAILABLE);
                }
            }
        }
        // 操作上架
        boolean b = updateById(ServiceItem.builder().id(serviceItemDTO.getId()).serviceState(serviceItemDTO.getServiceState()).build());
        // 处理下游
        List<ServiceItem> afterServiceItems = list(new QueryWrapper<ServiceItem>().lambda().eq(ServiceItem::getSourceId, serviceItemDTO.getId()).eq(ServiceItem::getIsDeleted, BusinessConstant.NO));
        for (ServiceItem afterServiceItem : afterServiceItems) {
            if (Objects.nonNull(afterServiceItem)) {
                ServiceItemDTO copyServiceItemDTO = new ServiceItemDTO();
                copyServiceItemDTO.setId(afterServiceItem.getId());
                copyServiceItemDTO.setServiceState(ServiceItemServiceStateEnum.DEFAULT);
                // 循环处理
                upShelves(copyServiceItemDTO);
            }
        }
        return b;
    }

    /**
     * 下架操作
     * @param serviceItemDTO
     * @return
     */
    private Boolean downShelves(ServiceItemDTO serviceItemDTO) {
        ServiceItem serviceItem = getById(serviceItemDTO.getId());
        if (Objects.nonNull(serviceItem)) {
            String serviceProviderType = serviceItem.getServiceProviderType();
            // 如果是综合服务，判断是否有绑定价目，且价目被展会使用
            checkExistPriceList(serviceItem);
            // 软删价目
            servicePriceListItemService.removeByServiceItemId(serviceItemDTO.getId());
            // 查询是否存在下游
            List<ServiceItem> afterServiceItemList = list(new QueryWrapper<ServiceItem>().lambda().eq(ServiceItem::getSourceId, serviceItem.getId()).eq(ServiceItem::getIsDeleted, BusinessConstant.NO));
            for (ServiceItem afterServiceItem : afterServiceItemList) {
                if (Objects.nonNull(afterServiceItem)) {
                    ServiceItemDTO copyServiceItemDTO = new ServiceItemDTO();
                    copyServiceItemDTO.setId(afterServiceItem.getId());
                    copyServiceItemDTO.setServiceState(dealAfterServiceState(serviceProviderType,serviceItemDTO.getServiceState()));
                    // 循环处理
                    downShelves(copyServiceItemDTO);
                }
            }
            // 操作下架
            return updateById(ServiceItem.builder().id(serviceItemDTO.getId()).serviceState(serviceItemDTO.getServiceState()).build());
        }
        return true;
    }

    /**
     * 处理服务状态
     * @param serviceProviderType serviceProviderType
     * @param serviceState
     * @return ServiceItemServiceStateEnum
     */
    private ServiceItemServiceStateEnum dealAfterServiceState(String serviceProviderType,ServiceItemServiceStateEnum serviceState) {
        if (Objects.nonNull(serviceProviderType) && ServiceItemServiceStateEnum.UNDER_SHELVES.eq(serviceState)) {
            // 如果是配套服务商，则下游状态为：配套服务已下架
            if (DataIsolationSystemSceneEnum.P_COMPOSITE_MATING.getCode().equals(serviceProviderType)) {
                return ServiceItemServiceStateEnum.MATING_UNDER_SHELVES;
            } else if (DataIsolationSystemSceneEnum.P_COMPOSITE_VENUE.getCode().equals(serviceProviderType)) {
                // 如果是综合服务，则下游状态为：综合服务已下架
                return ServiceItemServiceStateEnum.COMPOSITE_UNDER_SHELVES;
            } else {
                return ServiceItemServiceStateEnum.get(serviceProviderType);
            }
        } else {
            // 如果不是已下架，保留状态
            return ServiceItemServiceStateEnum.get(serviceProviderType);
        }
    }
}
